<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>go 标准包：context</title>
  
    <meta name="author" content="秀才">

    <!-- Le HTML5 shim, for IE6-8 support of HTML elements -->
    <!--[if lt IE 9]>
      <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
    <![endif]-->

    <!-- Le styles -->
    <link href="/assets/twitter/stylesheets/bootstrap.min.css" type="text/css" rel="stylesheet" media="all">
<link href="/assets/twitter/stylesheets/style.css" type="text/css" rel="stylesheet" media="all">
 
    <link href="/assets/twitter/widgets/google_prettify/stylesheets/twitter-bootstrap.css" type="text/css" rel="stylesheet" media="all">

    <!-- Le fav and touch icons -->
  <!-- Update these with your own images
    <link rel="shortcut icon" href="images/favicon.ico">
    <link rel="apple-touch-icon" href="images/apple-touch-icon.png">
    <link rel="apple-touch-icon" sizes="72x72" href="images/apple-touch-icon-72x72.png">
    <link rel="apple-touch-icon" sizes="114x114" href="images/apple-touch-icon-114x114.png">
  -->
  </head>

  <body>

    <div class="navbar">
      <div class="navbar-inner">
        <div class="container">
          <a class="brand" href="/">秀才</a>
          <ul class="nav">
            
              


  <li><a href="/tags">标签</a></li>


            
              


  <li><a href="/categories">分类</a></li>


            
              


  <li><a href="/about">关于我</a></li>


            
          </ul>
        </div>
      </div>
    </div>

    <div class="container">
      <div class="content">
        <div class="page-header">
  <h1>go 标准包：context </h1>
</div>

<div class="row">
  <div class="span12">
    <h3>用途</h3>

<p>学习这个包最重要的就是明白这个包的用途</p>

<p>在Google 内部，我们开发了 Context 包，专门用来简化 对于处理单个请求的多个 goroutine 之间与请求域的数据、取消信号、截止时间等相关操作，这些操作可能涉及多个 API 调用。</p>

<h3>API</h3>

<p><strong>父对象context的创建</strong>
Background 是所有 Context 对象树的根，它不能被取消</p>

<pre><code>func Background() Context
func TODO() Context
</code></pre>

<p>当请求处理函数返回时，与该请求关联的 Context 会被取消。 当使用多个副本发送请求时，可以使用 WithCancel取消多余的请求。 WithTimeout 在设置对后端服务器请求截止时间时非常有用。 下面是这三个函数的声明：</p>

<pre><code>// WithCancel returns a copy of parent whose Done channel is closed as soon as
// parent.Done is closed or cancel is called.
func WithCancel(parent Context) (ctx Context, cancel CancelFunc)

// A CancelFunc cancels a Context.
type CancelFunc func()

// WithTimeout returns a copy of parent whose Done channel is closed as soon as
// parent.Done is closed, cancel is called, or timeout elapses. The new
// Context's Deadline is the sooner of now+timeout and the parent's deadline, if
// any. If the timer is still running, the cancel function releases its
// resources.
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)
</code></pre>

<p>WithValue 函数能够将请求作用域的数据与 Context 对象建立关系。声明如下：</p>

<pre><code>// WithValue returns a copy of parent whose Value method returns val for key.
func WithValue(parent Context, key interface{}, val interface{}) Context
</code></pre>

<h3>示例</h3>

<p>我们通过<code>WithCancel</code>来结束子对象的运行。</p>

<pre><code class="language-go">type person struct {
	Name string
	Age  int
}

func printP(ctx context.Context, persons map[int]person) {
	var i int
	for {
		select {
		case &lt;-ctx.Done():
			fmt.Println(60, persons)
			return
		default:
			i++
			time.Sleep(time.Millisecond * 200)
			fmt.Println(i)
		}
	}
}

func getPerson() (persons map[int]person) {
	persons = map[int]person{
		1: {Name: &quot;zhangsan&quot;, Age: 12},
		2: {Name: &quot;lisi&quot;, Age: 14},
	}
	fmt.Printf(&quot;75: %p\n&quot;, persons)
	return
}

func TestCustom(t *testing.T) {
	ctx := context.Background()
	ctx, cancel := context.WithCancel(ctx)
	persons := getPerson()
	go printP(ctx, persons)
	persons[1] = person{
		Name: &quot;xxx&quot;,
		Age:  1,
	}
	fmt.Printf(&quot;89: %p\n&quot;, persons)
	time.Sleep(time.Second * 2)
	cancel()
	select {} //暂且用死锁稳住函数，不让函数结束
}
</code></pre>

    <hr>
    <div class="pagination">
      <ul>
        <ul>
          
            <li class="prev"><a href="/go/go-%E6%A0%87%E5%87%86%E5%8C%85%EF%BC%9Afmt/" title="go 标准包：fmt">&larr; Previous</a></li>
          
          

            <li><a href="/archive">Archive</a></li>

          
            <li class="next"><a href="/go/go-%E6%A0%87%E5%87%86%E5%8C%85%EF%BC%9Async/" title="go 标准包：sync">Next &rarr;</a></li>
          
          
        </ul>
      </ul>
    </div>
    <hr>
    
  </div>
  
  <!-- <div class="span4">
    <h4>Published</h4>
    <div class="date"><span>2016-12-16</span></div>
    <br>
    <h4>Categories</h4>
    <ul class="tag_box">
    
      <li>
  <a href="/categories/#go-ref">go <span>7</span></a>
</li>
    
    </ul>
    <br>
    <h4>Tags</h4>
    <ul class="tag_box">
    
      <li>
  <a href="/tags/#go-ref">go <span>7</span></a>
</li>
    
      <li>
  <a href="/tags/#%E5%B9%B6%E5%8F%91-ref">并发 <span>6</span></a>
</li>
    
    </ul>
  </div> -->
</div>

      </div>

      <footer>
        <p>&copy; 秀才 2013 
          with help from <a href="http://github.com/wendal/gor" target="_blank" title="Gor -- Fast Blog">Gor</a>
          and <a href="http://twitter.github.com/bootstrap/" target="_blank">Twitter Bootstrap</a>
		  and Idea from <a href="http://ruhoh.com" target="_blank" title="The Definitive Technical Blogging Framework">ruhoh</a>
        </p>
      </footer>

    </div> <!-- /container -->
    <!-- <script src="//cdnjscn.b0.upaiyun.com/libs/prettify/r298/prettify.min.js"></script> -->
    <script src="http://cdn.staticfile.org/prettify/r298/prettify.min.js"></script>
    <script>
      var pres = document.getElementsByTagName("pre");
      for (var i=0; i < pres.length; ++i) {
        pres[i].className = "prettyprint linenums";
      }
      prettyPrint();
    </script>
    
    
  </body>
</html>
